package com.oneday.nuo.base.security;


import com.oneday.nuo.base.common.CommonStatic;
import com.oneday.nuo.base.security.auth.*;
import com.oneday.nuo.base.security.interceptor.NuoFilterSecurityInterceptor;
import com.oneday.nuo.base.security.login.NuoAuthenticationProcessingFilter;
import com.oneday.nuo.base.security.user.NuoUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 配置文件
 * @Author: liushuai
 * @Date: 2021/3/14 22:24
 * @param : * @param null
 * @return :
 **/

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private NuoUserDetailsService nuoUserDetailsService;


    @Autowired
    private NuoAuthenticationProcessingFilter nuoAuthenticationProcessingFilter;

    @Autowired
    private NuoNoLoginHander nuoNoLoginHander;
    @Autowired
    private NuoFilterSecurityInterceptor nuoFilterSecurityInterceptor;
    @Autowired
    private NuoAccessDeniedHander nuoAccessDeniedHander;

    @Autowired
    private NuoLoginFailureHander nuoLoginFailureHander;
    @Autowired
    private NuoLoginSuccessHander nuoLoginSuccessHander;
    /**
     * 从容器中取出 AuthenticationManagerBuilder，执行方法里面的逻辑之后，放回容器
     * @Author: liushuai
     * @Date: 2021/3/11 22:42
     * @param : * @param authenticationManagerBuilder
     * @return :void
     **/
    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        //authenticationManagerBuilder.userDetailsService(nuoUserDetailsService);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * 在 UsernamePasswordAuthenticationFilter 之前添加 JwtAuthenticationTokenFilter
         */
        http.addFilterBefore(nuoFilterSecurityInterceptor, UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(nuoAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class);
        http.csrf().disable().cors().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                // 角色校验时，会自动拼接 "ROLE_"
                .antMatchers("/v2/api-docs").permitAll()
                .antMatchers("/captcha/get").permitAll()
                .antMatchers("/captcha/check").permitAll()
                .anyRequest().authenticated()   // 任何请求,登录后可以访问
                .and().formLogin().loginProcessingUrl(CommonStatic.LOGIN_URL)
                .successHandler(nuoLoginSuccessHander)
                .failureHandler(nuoLoginFailureHander)
                .and().headers().cacheControl();

        // 处理异常情况：认证失败和权限不足
        http.exceptionHandling().authenticationEntryPoint(nuoNoLoginHander).accessDeniedHandler(nuoAccessDeniedHander);

    }


    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(false);
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }

    public NuoFilterSecurityMetadataSource getNuoFilterSecurityMetadataSource() {
        NuoFilterSecurityMetadataSource sourceService = new NuoFilterSecurityMetadataSource();

        return sourceService;
    }
}
